package ch.wsl.postgres2mapperdao

/**
 * 
 * Postgres2mapperdao
 * 
 * @author Andrea Minetti
 *
 * 21 Sep 2012
 * 
 */

import ch.wsl.postgres2mapperdao.model._
import ch.wsl.postgres2mapperdao.common.DatabaseConnection
import RichFile.enrichFile
import java.io.File
import org.clapper.argot._

object Starter {
	
  
	import ArgotConverters._

	val parser = new ArgotParser(
			"postgres2mapperdao",
			preUsage=Some("Postgres2mapperdao: Version 0.1. Copyright (c) " +
                  "2012, Andrea Minetti. "),
            postUsage=Some("\n\nEXAMPLES:\n"+
            				"postgres2mapperdao -U <user> -P <password> -y -s <schema>\n"+
            				"postgres2mapperdao -U <user> -P <password> -d -s <schema> [-t <table>]\n"+
            				"postgres2mapperdao -U <user> -P <password> -v -s <schema> [-t <table>] -p <package>\n"+
            				"postgres2mapperdao -U <user> -P <password> -g -s <schema> [-t <table>] -p <package> -o <outdir>\n"+
            				"")
			)

	val showTypes = parser.flag[Boolean](List("y", "show-types"),"Show types used in your DB")
	
	val generate = parser.flag[Boolean](List("g", "generate"),"Generate code")
	
	val view = parser.flag[Boolean](List("v", "view"),"View class")
	
	val describe = parser.flag[Boolean](List("d", "describe"),"View description")
                                      
    val schema = parser.option[String](List("s", "schema"), "schema","Specify schema")
    
    val table = parser.option[String](List("t", "table"), "table","Specify table")
    
    val out = parser.option[String](List("o", "out"), "directory","Specify where to save classes")
    
    val packageName = parser.option[String](List("p", "package"), "package","Specify the package")
    
    val user = parser.option[String](List("U", "user"), "user","Specify the user")
    
    val password = parser.option[String](List("P", "password"), "password","Specify the password")
    
    val database = parser.option[String](List("d", "database"), "database","Specify the database")
    
  
  
	lazy val tableDao = new TableDao(DatabaseConnection.mapperDao, DatabaseConnection.queryDao)
  
	def main(args: Array[String]) {
	  
		
		try {
		  
		  var didSomething = false
		  
	      parser.parse(args)
	      

	      DatabaseConnection.connect(user.value.get, password.value.get, database.value.get)

	      
	      if(showTypes.value.isDefined && schema.value.isDefined) {
	    	  didSomething = true
	    	  showUsedTypes(schema.value.get)
	      } else if((view.value.isDefined || (generate.value.isDefined && out.value.isDefined ))  && packageName.value.isDefined  && schema.value.isDefined) {
	        
	        if(generate.value.isDefined) {
	          if(table.value.isDefined) {
	            didSomething = true
	            write(schema.value.get, table.value.get, packageName.value.get, out.value.get)
	          } else {
	            didSomething = true
	            write(schema.value.get, packageName.value.get, out.value.get)
	          }
	        }
	        
	        if(view.value.isDefined) {
	          if(table.value.isDefined) {
	            didSomething = true
	            print(schema.value.get, table.value.get, packageName.value.get)
	          } else {
	            didSomething = true
	            print(schema.value.get, packageName.value.get)
	          }
	        }
	        
	      } else if(describe.value.isDefined) {
	    	  if(table.value.isDefined) {
	    		  didSomething = true
	    		  showTableStructure(table.value.get)
	    	  } else if(schema.value.isDefined) {
	    		  didSomething = true
	    		  showSchemaStructure(schema.value.get)
	    	  }
	      }
	      
	      if(!didSomething) {
	        parser.usage
	      }
	        
	    }
	
	    catch {
	      case e => parser.usage()
	    }
		
		

		
	}
	
	
	def print(schema: String, pack: String) = {
		
        for(table <- tableDao.all(schema))
        	println(MapperDaoComposer.compose(table,pack))
	  
	}
	
	def print(schema: String, table: String, pack: String) = {
		
        val t = tableDao.retrieve(table).get
        println(MapperDaoComposer.compose(t,pack))
	  
	}
	
	def write(schema: String, pack: String, outDir: String ) = {
	  
        for(table <- tableDao.all(schema)) {
        	println("Writing " + outDir + table.table_class + ".scala" + " from table " + table.table_schema + "." + table.table_name)
        	val file = new File(outDir + table.table_class + ".scala")
        	file.text = MapperDaoComposer.compose(table,pack)
        	
        }
	  
	}
	
	def write(schema: String, table: String, pack: String, outDir: String) = {
		
		val t = tableDao.retrieve(table).get
		println("Writing " + outDir + t.table_class + ".scala" + " from table " + t.table_schema + "." + t.table_name)
        val file = new File(outDir + t.table_class + ".scala")
        file.text = MapperDaoComposer.compose(t,pack)
	  
	}
	
	
	def showUsedTypes(schema: String) = {
		
	  var l = List[String]()
	  
	  for(c <- tableDao.all(schema)) {

    		for(p <- c.fields) {
    			if(!l.contains(p.data_type))
    				l = l ::: List(p.data_type)
    		}
        	
        }
		
	  	println("\n\nTypes in schema " + schema +": \n")
		for (li <- l) {
		  println("    " + li)
		}
	}
	
	def showSchemaStructure(schema: String) = {
	  
	  showTables(tableDao.all(schema))
	  
	}
	
	def showTableStructure(table: String) = {
	  
		showTables(List(tableDao.retrieve(table).get))
		
	}
	
	def showTables(tables: List[Table]) = {
			for(c <- tables) {
        	println("\n\nTABLE: " + c.table_name)
        	println("COLUMNS: ")

    		for(p <- c.fields) {
    			println("   " + p.column_name)
    		}
        	
        	println("PRIMARY KEYS: ")
        	if(!c.primaryKeys.isEmpty) {
        		for(p <- c.primaryKeys.get) {
        			println("   " + p.column_name)
        		}
        	}
        	println("FOREIGN KEYS: ")
        	for(f <- c.foreignKeys) {
        		println("   REFERENCES TABLE: " + f.refExtColumns.first.table_name)
        		for(fk <- f.refColumns) {
        			println("      " + fk.column_name)
        		}
        	}
        }
	}
}